Instead of returning a FeatureCollection of sampledPoints around each buffered point, modify the samplePoints function so that it:
Takes the mean of all the samplePoints within a bufferzone using the same “reduceColumns” method I showed you earlier.
Creates a feature with a null geometry and the bufferzone mean assigned to the buffered point ID from which the points were sampled.
Uses this new function and a mapping operation to create the meanPopDensFC variable without needing to compute sampledPoints, meanPopDens, or meanPopDensList.
time:30 minutes
// Function to sample random points within each buffered area
var samplePoints = function (feature) {
var geometry = feature.geometry();
var randomPoints = ee.FeatureCollection.randomPoints(geometry, 10);
var sampledPoints = popDensYearBuffered.sampleRegions({
collection: randomPoints,
scale: 1000,
tileScale: 16
})
// Add the buffered area ID to each sampled point
sampledPoints = sampledPoints.map(function(point) {
return point.set('BufferedAreaID', feature.get('ID'));
});
// Calculate the mean 'population_density' for each group
var meanPopDens = sampledPoints.reduceColumns({
reducer: ee.Reducer.mean(),
selectors: ['population_density']
});
return ee.Feature(null, {
'BufferedAreaID': feature.get('ID'),
'mean': meanPopDens.get('mean')
});
};
// Sample 10 random points within each buffered area and calculate the mean population density
var meanPopDensFC = bufferedPoints.map(samplePoints);If we take the mean inside of samplePoints we could also do the filtering inside the function and return geometries without needing to access a bufferedPoint’s ID.
Modify the “samplePoints” function so that it: 1. doesn’t need to assign an “ID” value to “BufferedAreaID”. 2. Filters out mean population density values less than 100 people per sq. km. 3. returns a “highDensityPoint” candidate directly.
time: 30 minutes
// Function to sample random points within each buffered area
var samplePoints = function (feature) {
var geometry = feature.geometry();
var randomPoints = ee.FeatureCollection.randomPoints(geometry, 10);
var sampledPoints = popDensYearBuffered.sampleRegions({
collection: randomPoints,
scale: 1000,
tileScale: 16
})
// Calculate the mean 'population_density' for each group
var meanPopDens = sampledPoints.reduceColumns({
reducer: ee.Reducer.mean(),
selectors: ['population_density']
});
// Filter out mean population density values
// less than 100 people per sq. km.
var mean = meanPopDens.get('mean');
if (mean < 100) {
return null;
}
// return a "highDensityPoint" candidate
return ee.Feature(geometry, {
'mean': mean
});
};
// Map highDensityPoints to get candidate points
var highDensityPoints = bufferedPoints.map(samplePoints)
.filter(ee.Filter.neq(null));Remove ID assignment from 1st part of the script by:
Rename the “bufferAndSetID” function to just “bufferPoint”.
Modify this new “bufferPoint” function so that it takes in a point feature instead of an index and then just buffers this point instead of both buffering and doing index assignment.
Map this new function over the intersectionPoints featureCollection to get a new “bufferedPoints” featureCollection that doesn’t have id’s.
time: 20 minutes
Another way to simplify might be to create a new module to store functions we have created in this script.
time: 10 minutes
To include this module we will add the following line to the beginning of our port finding script:
time: 20 minutes
Here is what we added to the helper module:
exports.lineToPoint = function(feature) {
// Get the geometry
var geom = feature.geometry();
// Get the centroid of the geometry
var centroid = geom.centroid();
// Create a new point feature
var pointFeature = ee.Feature(centroid, feature.toDictionary());
return pointFeature;
};and here is how we call this function:
We would also like to modularize other functions we have created. For example, “bufferPoint”.
put “bufferPoint” into your helper module and call it from your script.
time: 10 minutes
The “samplePoints” function is doing alot of work for us. Can we decompose this function and move some of its pieces out to our module?
time: 20 minutes
Added to “Helpers”:
// Function to calculate the mean 'population_density' for each group of sampled points
exports.calculateMeanDensity = function (popDensYearBuffered, randomPoints) {
var sampledPoints = popDensYearBuffered.sampleRegions({
collection: randomPoints,
scale: 1000,
tileScale: 16
});
var meanPopDens = sampledPoints.reduceColumns({
reducer: ee.Reducer.mean(),
selectors: ['population_density']
});
return meanPopDens.get('mean');
};// Function to sample random points within each buffered area
var samplePoints = function (feature) {
var geometry = feature.geometry();
var randomPoints = ee.FeatureCollection.randomPoints(geometry, 10);
var mean = hlp.calculateMeanDensity(popDensYearBuffered, randomPoints);
// Filter out mean population density values less than 100 people per sq. km.
if (mean < 100) {
return null;
}
// return a "highDensityPoint" candidate
return ee.Feature(geometry, {
'mean': mean
});
};Further simplify the “samplePoints” function by taking the logic that filters the population density values to return highDensityPoints into a function called “filterHighDensityPoints”
time: 10 minutes
// Function to sample random points within each buffered area
var samplePoints = function (feature) {
var geometry = feature.geometry();
var randomPoints = ee.FeatureCollection.randomPoints(geometry, 10);
var mean = hlp.calculateMeanDensity(popDensYearBuffered, randomPoints);
// return filtered mean population density values less than 100 people per sq. km.
return hlp.filterHighDensityPoints(geometry, mean);
};Write a short description of what each column in the profiler tab is describing.
We can do a more manual style of profiling to hone in on how changing the way we are getting intersection points speeds up or slows down the function.
// Get a timestamp before calling the function
var start = Date.now();
// Call the function
// Get a timestamp after calling the function
var end = Date.now();
// Calculate the execution time
var executionTime = end - start;
print('Execution time: ', executionTime + ' ms');